﻿using System;
using System.Text;


public struct SendData
{
    public long m_CreateTime;
    public string m_Str;
    public int m_V;
    public MyUdpSlice m_Slice;
}

public class MyUdpSlice
{
    public byte[] m_Data = new byte[UdpHelper.UDP_Slice_Head_Len + UdpHelper.UDP_Slice_Max_Body_Size];
    public int m_BodyLen;

    public bool m_IsRemoteResp;
    public long m_LastSentTime;
    public int m_ReSendCount;
}


public class MyUdpPacket
{
    public MyUdpSlice[] m_Slices;

    public ushort GetMsgId()
    {
        return BitConverter.ToUInt16(m_Slices[0].m_Data, 0);
    }

    public bool CheckAllReady(out string str)
    {
        str = "";

        int totalLen = 0;
        for (int i = 0; i < m_Slices.Length; ++i)
        {
            var slice = m_Slices[i];
            if (null == slice || !slice.m_IsRemoteResp)
                return false;

            totalLen += slice.m_BodyLen;
        }

        byte[] bytes = new byte[totalLen]; //todo: 复用
        int offset = 0;
        for (int i = 0; i < m_Slices.Length; ++i)
        {
            var slice = m_Slices[i];
            Buffer.BlockCopy(slice.m_Data, UdpHelper.UDP_Slice_Head_Len, bytes, offset, slice.m_BodyLen);
            offset += slice.m_BodyLen;
        }
        str = Encoding.UTF8.GetString(bytes);

        return true;
    }

}


public static class UdpHelper
{
    public const int UDP_Slice_Head_Len = 8;
    public const int UDP_Slice_Max_Body_Size = 512;

    public static bool IsUdpSliceReady(byte[] buff, int readedLen, int notReadLen, out int opCode, out int bodyLen)
    {
        opCode = 0;
        bodyLen = 0;

        if (notReadLen < UDP_Slice_Head_Len)
            return false;

        //msgId: 2-byte, [-32768, 32767]或[0, 65535]
        //opCode: 1-byte, [-128, 127]或[0, 255]
        //bodyLen: 1-byte
        //sliceIndex: 2-byte
        //sliceCount: 2-byte

        opCode = buff[readedLen + 2];
        bodyLen = buff[readedLen + 3];
        if (notReadLen < UDP_Slice_Head_Len + bodyLen)
            return false;

        return true;
    }

}
